/* 
 * File:   main.cpp
 * Author: zhouzhao
 *
 * Created on December 21, 2011, 10:48 AM
 */

#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <time.h>
#include <iomanip>
#include <algorithm>

#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/assert.hpp>

#include "global.h"
#include "devNode.h"
#include "cuda.h"
#include "partition.h"

using namespace std;

int findNode(string name){
    
    int index = -1;
    for(int i = 0; i < allCount; i++){
        if(!name.compare(nodeAll[i]->name)){
            index = nodeAll[i]->index;
            break;
        }
    }
    return index;
}

int containChar(char c, char* trim){
    int flag = 0;
    for(unsigned int i = 0; i < string(trim).length(); i++){
        if(c == trim[i]){
            flag = 1;
            break;
        }
    }
    return flag;
}

string trimEnd(string oldStr, char* trim){
    
    string::iterator it = oldStr.end()-1;
    
    while(containChar(*it, trim) && it >= oldStr.begin()){
        oldStr.erase(it);
        it--;
    }
    return oldStr;
}

//verify if the gate is defined
int gIsDefined(string gate){
    int flag = -1;
    map<GType, string>::iterator it;
    for(it = gMap.begin(); it != gMap.end(); it++){
        if(!gate.compare((*it).second)){
            flag = (int)((*it).first);
            break;
        }
    }
    return flag;
}

//verify if the keyword is defined
int kIsDefined(string keyword){
    int flag = -1;
    map<KWord, string>::iterator it;
    for(it = kMap.begin(); it != kMap.end(); it++){
        if(!keyword.compare((*it).second)){
            flag = (int)((*it).first);
            break;
        }
    }
    return flag;
}

//verify if the module is defined
int mIsDefined(string module){
    int flag = -1;
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        if(!module.compare(moduleAll[i]->name)){
            flag = i;
            break;
        }
    }
    return flag;
}

//print fanin and fanout of one node
void printFF(Node* np){
    
    vector<Node*>::iterator it;
    cout<<"fanin: ";
    for(it = np->upperNodes.begin(); it < np->upperNodes.end(); it++){
        cout<<(*it)->name<<" ";
    }
    cout<<"fanout: ";
    for(it = np->downNodes.begin(); it < np->downNodes.end(); it++){
        cout<<(*it)->name<<" ";
    }
}

void printNodeToFile(void){
    
    ofstream result;
    module* mp;
    Node** npp;
    unsigned int nodeSum = 0;
	unsigned int gateSum = 0;
	unsigned int ffSum = 0;
    
    result.open("result.txt");
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        nodeSum = nodeSum + mp->allNum;
		gateSum = gateSum + mp->allNum - mp->inputNum - mp->ffMap.size();
		ffSum = ffSum + mp->ffMap.size();

        npp = mp->nAll;
        result<<"module "<<mp->name;
        for(unsigned int i = 0; i < 80 - mp->name.length() - 7; i++) result<<"-";
        result<<endl;
        result<<"index\ttype\tname\tgate\tfanin\tfanout\tlevel\tlogic"<<endl;
        for(int i = 0; i < 80; i++) result<<"-";
        result<<endl;
        
        for(int i = 0; i < mp->allNum; i++){
			result<<npp[i]->modIndex<<","<<npp[i]->index<<"\t"<<nMap[npp[i]->type]<<setw(20)
                    <<npp[i]->name<<setw(20)<<gMap[npp[i]->gate]<<"\t"
                    <<npp[i]->fanin<<"\t"<<npp[i]->fanout<<"\t"
                    <<npp[i]->level<<"\t"<<lMap[npp[i]->logic]<<endl;
        }

        result<<"node number: "<<mp->allNum<<endl;
        result<<"input number: "<<mp->inputNum<<endl;
        result<<"output number: "<<mp->outputNum<<endl;
        result<<"flip flop: "<<mp->ffMap.size()<<endl;

        result<<"input node are: ";
        for(int i = 0; i < mp->inputNum; i++){
            result<<mp->nInput[i]->name<<" ";
        }
        result<<endl;

        result<<"output node are: ";
        for(int i = 0; i < mp->outputNum; i++){
            result<<mp->nOutput[i]->name<<" ";
        }
        result<<endl;
        result<<endl;
 /*   
    for(int i = 0; i < allCount; i++){
        cout<<nodeAll[i]->name<<" ";
        printFF(nodeAll[i]);
        cout<<endl;
    }
  */
    }
    
    result<<"summary: "<<endl;
    result<<"total number of node is "<<nodeSum<<endl;
    result<<"max level is "<<maxLevel<<endl;
	result<<"total number of gate is "<<gateSum<<endl;
	result<<"total number of flip-flop is "<<ffSum<<endl;
    result.close();
}

void printModule(){
    
    map<string, vector<Node*> >::iterator it;
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        cout<<"module "<<moduleAll[i]->name<<endl;
        cout<<moduleAll[i]->allNum<<" "<<moduleAll[i]->inputNum<<" "<<moduleAll[i]->outputNum<<endl;
        for(it = moduleAll[i]->inputMap.begin(); it != moduleAll[i]->inputMap.end(); it++){
            cout<<(*it).first<<": ";
            for(unsigned int i = 0; i < (*it).second.size(); i++){
                if((*it).second[i]->upperNodes.size() > 0)
                cout<<(*it).second[i]->name<<"->"<<(*it).second[i]->upperNodes[0]->name<<" ";
            }
            cout<<endl;
        }
        for(it = moduleAll[i]->outputMap.begin(); it != moduleAll[i]->outputMap.end(); it++){
            cout<<(*it).first<<": ";
            for(unsigned int i = 0; i < (*it).second.size(); i++){
                if((*it).second[i]->downNodes.size() > 0)
                cout<<(*it).second[i]->name<<"->"<<(*it).second[i]->downNodes[0]->name<<" ";
            }
            cout<<endl;
        }
    }
}

void initGlobal(void){
    
    nodeAll = NULL;
    nodeInput = NULL;
    nodeOutput = NULL;
    
    allCount = 0;
    inputCount = 0;
    outputCount = 0;
    wireCount = 0;
    maxLevel = 0;
    
    boost::assign::insert(gMap)
        (IPT, "IPT")(BRCH, "BRCH")
        (INVX1, "INVX1")(INVX2, "INVX2")
        (INVX4, "INVX4")(INVX8, "INVX8")
        (AND2X1, "AND2X1")(AND2X2, "AND2X2")
        (NAND2X1, "NAND2X1")(NAND3X1, "NAND3X1")
        (OR2X1, "OR2X1")(OR2X2, "OR2X2")
        (NOR2X1, "NOR2X1")(NOR3X1, "NOR3X1")
        (XOR2X1, "XOR2X1")(XNOR2X1, "XNOR2X1")
        (AOI21X1, "AOI21X1")(AOI22X1, "AOI22X1")
        (OAI21X1, "OAI21X1")(OAI22X1, "OAI22X1")
        (DFFNEGX1, "DFFNEGX1")(DFFPOSX1, "DFFPOSX1")(DFFSR, "DFFSR")
        (BUFX2, "BUFX2")(BUFX4, "BUFX4")
        (FAX1, "FAX1")(FAC, "FAC")(FAS, "FAS")
        (HAX1, "HAX1")(HAC, "HAC")(HAS, "HAS")
        (MUX2X1, "MUX2X1")(NA, "NA");
    BOOST_ASSERT(gMap.size() == 33);
    
    boost::assign::insert(nMap)
        (GATE, "GATE")(PI, "PI") 
        (FB, "FB")(PO, "PO") 
        (PPI, "PPI")(PPO, "PPO")
        (DUMMY, "DUMMY");
    BOOST_ASSERT(nMap.size() == 7);
    
    boost::assign::insert(lMap)
        (ZERO, "0")(DBAR, "~D")
        (D, "D")(ONE, "1")
        (X, "X");
    BOOST_ASSERT(lMap.size() == 5);
    
    boost::assign::insert(kMap)
        (MODULE, "module")(INPUT, "input")
        (OUTPUT, "output")(WIRE, "wire")
        (ASSIGN, "assign")(ENDMODULE, "endmodule");
    BOOST_ASSERT(kMap.size() == 6);
}

//check if node is ready to compute its level
int nodeReady(Node* np){
    int flag = 1;
    vector<Node*>::iterator it;
    for(it = np->upperNodes.begin(); it < np->upperNodes.end(); it++){
        if((*it)->level == -1){
            flag = 0;
            break;
        }
    }
    return flag;
}

//check if node is ready to compute its logic
int nodeLogicReady(Node* np){
    int flag = 1;
    vector<Node*>::iterator it;
    for(it = np->upperNodes.begin(); it < np->upperNodes.end(); it++){
        if((*it)->logic == X){
            flag = 0;
            break;
        }
    }
    return flag;
}

//compute level of one node
int nodeCompute(Node* np){
    int level = -1;
    vector<Node*>::iterator it;
    for(it = np->upperNodes.begin(); it < np->upperNodes.end(); it++){
        if((*it)->level > level){
            level = (*it)->level;
        }
    }
    return level + 1;
}

int nodeLogic(Node* np){
    
    int logic = X;
    if(np->gate == INVX1 || np->gate == INVX2 || np->gate == INVX4 || np->gate == INVX8){
        logic = ~(np->upperNodes[0]->logic);
    }else if(np->gate == AND2X1 || np->gate == AND2X2 || np->gate == HAC){
        logic = (np->upperNodes[0]->logic) & (np->upperNodes[1]->logic);
    }else if(np->gate == NAND2X1){
        logic = ~((np->upperNodes[0]->logic) & (np->upperNodes[1]->logic));
    }else if(np->gate == NAND3X1){
        logic = ~((np->upperNodes[0]->logic) & (np->upperNodes[1]->logic) &
                (np->upperNodes[2]->logic));
    }else if(np->gate == OR2X1 || np->gate == OR2X2){
        logic = (np->upperNodes[0]->logic) | (np->upperNodes[1]->logic);
    }else if(np->gate == NOR2X1){
        logic = ~((np->upperNodes[0]->logic) | (np->upperNodes[1]->logic));
    }else if(np->gate == NOR3X1){
        logic = ~((np->upperNodes[0]->logic) | (np->upperNodes[1]->logic) |
                (np->upperNodes[2]->logic));
    }else if(np->gate == XOR2X1 || np->gate == HAS){
        logic = (np->upperNodes[0]->logic) ^ (np->upperNodes[1]->logic);
    }else if(np->gate == XNOR2X1){
        logic = ~((np->upperNodes[0]->logic) ^ (np->upperNodes[1]->logic));
    }else if(np->gate == AOI21X1){
        logic = ~((np->upperNodes[0]->logic) | ((np->upperNodes[1]->logic) & (np->upperNodes[2]->logic)));
    }else if(np->gate == AOI22X1){
        logic = ~(((np->upperNodes[0]->logic) & (np->upperNodes[1]->logic)) |
                ((np->upperNodes[2]->logic) & (np->upperNodes[3]->logic)));
    }else if(np->gate == OAI21X1){
        logic = ~((np->upperNodes[0]->logic) & ((np->upperNodes[1]->logic) | (np->upperNodes[2]->logic)));
    }else if(np->gate == OAI22X1){
        logic = ~(((np->upperNodes[0]->logic) | (np->upperNodes[1]->logic)) &
                ((np->upperNodes[2]->logic) | (np->upperNodes[3]->logic)));
    }else if(np->gate == BUFX2 || np->gate == BUFX4){
        logic = np->upperNodes[0]->logic;
    }else if(np->gate == FAS){
        logic = (np->upperNodes[0]->logic) ^ (np->upperNodes[1]->logic)
                ^ (np->upperNodes[2]->logic);
    }else if(np->gate == FAC){
        logic = ((np->upperNodes[0]->logic) & (np->upperNodes[1]->logic)) | 
                ((np->upperNodes[1]->logic) & (np->upperNodes[2]->logic)) |
                ((np->upperNodes[0]->logic) & (np->upperNodes[2]->logic));
    }else if(np->gate == MUX2X1){
        if(np->upperNodes[0]->logic == ZERO){
            logic = np->upperNodes[1]->logic;
        }else{
            logic = np->upperNodes[2]->logic;
        }
    }
        
    return logic & 3;
}

int nodeLevelize(){
    
    queue<Node*> nodeQ;
    vector<Node*>::iterator it, itf;
    map<Node*, Node*>::iterator itt;
    Node* np;
    int level = 0;
    module* mp = moduleAll.back();
    Node** npp = mp->nInput;
    
    //initialize the input node in top module
    for(int i = 0; i < mp->inputNum; i++){
        npp[i]->level = 0;
        for(it = npp[i]->downNodes.begin(); it < npp[i]->downNodes.end(); it++){
            if(nodeReady((*it))){
                nodeQ.push((*it));
            }
        }
    }
    
    //initialize the flip-flop node in all module
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        for(itt = mp->ffMap.begin(); itt != mp->ffMap.end(); itt++){
            np = (*itt).second;
            np->level = 0;
            for(it = np->downNodes.begin(); it < np->downNodes.end(); it++){
                if(nodeReady((*it))){
                    nodeQ.push((*it));
                }
            }
        }
    }
    
    //initialize the dummy node in all module
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        for(itf = mp->nFloat.begin(); itf < mp->nFloat.end(); itf++){
            (*itf)->level = 0;
            for(it = (*itf)->downNodes.begin(); it < (*itf)->downNodes.end(); it++){
                if(nodeReady((*it))){
                    nodeQ.push((*it));
                }
            }
        }
    }
    
    //process the queue
    while(nodeQ.size() != 0){
        np = nodeQ.front();
        nodeQ.pop();
        np->level = nodeCompute(np);
        if(np->level > level) level = np->level;
        for(it = np->downNodes.begin(); it < np->downNodes.end(); it++){
            if(nodeReady((*it))){
                nodeQ.push((*it));
            }
        }
    }
    
    maxLevel = level;
    return 0;
}

//perform the logic simulation of one cone
void vertexLogicSim(vertex* vp){

	for(int i = 1; i <= vp->bottomLevel - vp->topLevel; i++){
		for(int j = 0; j < vp->subptr[i].size(); j++){
			vp->subptr[i][j]->logic = (LType)nodeLogic(vp->subptr[i][j]);
		}
	}
}

int elabLogicSim(int cycle){
    
    queue<Node*> nodeQ;
    vector<Node*>::iterator it, itf;
    map<Node*, Node*>::iterator itt;
    Node* np;
    module* mp = moduleAll.back();
    Node** npp = mp->nInput;
    
	//clearup node in all module
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        for(int j = 0; j < moduleAll[i]->allNum; j++){
            np = moduleAll[i]->nAll[j];
            if(np->type != PPO) np->logic = X;
        }
    }
    
    //initialize the queue with all inputs of top module
    for(int i = 0; i < mp->inputNum; i++){
        if(matrix[cycle*(mp->inputNum)+i] == 0){
            npp[i]->logic = ZERO;
        }else{
            npp[i]->logic = ONE;
        }
        for(it = npp[i]->downNodes.begin(); it < npp[i]->downNodes.end(); it++){
            if(nodeLogicReady((*it))){
                nodeQ.push((*it));
            }
        }
    }
    
    //initialize the queue with flip flop of all module
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        for(itt = mp->ffMap.begin(); itt != mp->ffMap.end(); itt++){
            np = (*itt).second;
            if(cycle == 0){
                np->logic = ZERO;
            }else{
                np->logic = (*itt).first->logic;
            }
            for(it = np->downNodes.begin(); it < np->downNodes.end(); it++){
                if(nodeLogicReady((*it))){
                    nodeQ.push((*it));
                }
            }
        }
    }
    
    //initialize the queue with dummy nodes of all module
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        for(itf = mp->nFloat.begin(); itf < mp->nFloat.end(); itf++){
            //logic value of dummy node is constant
            for(it = (*itf)->downNodes.begin(); it < (*itf)->downNodes.end(); it++){
                if(nodeLogicReady((*it))){
                    nodeQ.push((*it));
                }
            }
        }
    }
    
    //process the queue
    while(nodeQ.size() != 0){
        np = nodeQ.front();
        nodeQ.pop();
        np->logic = (LType)nodeLogic(np);
        for(it = np->downNodes.begin(); it < np->downNodes.end(); it++){
            if(nodeLogicReady((*it))){
                nodeQ.push((*it));
            }
        }
    }
    
    return 0;
}

void partitionLogicSim(int cycle){

	map<int, vector<vertex> >::iterator mit;
	map<Node*, Node*>::iterator it;

	module* mp = moduleAll.back();
	Node** npp = mp->nInput;
	vertex* vp;
	Node* np;

	//initialize the PI node
	for(int i = 0; i < mp->inputNum; i++){
		if(matrix[cycle*(mp->inputNum)+i] == 0){
			npp[i]->logic = ZERO;
		}else{
			npp[i]->logic = ONE;
		}
	}

	//initialize the PPI node
	for(int i = 0; i < moduleAll.size(); i++){
		mp = moduleAll[i];
		for(it = mp->ffMap.begin(); it != mp->ffMap.end(); it++){
			np = (*it).second;
			if(cycle == 0){
				np->logic = ZERO;
			}else{
				np->logic = (*it).first->logic;
			}
		}
	}

	for(mit = nPartition.begin(); mit != nPartition.end(); mit++){
		for(int i = 0; i < (*mit).second.size(); i++){
			vp = &((*mit).second[i]);
			vertexLogicSim(vp);
		}
	}
}

int cpuLogicSim(string vector, int option){
    
    module* mp = moduleAll.back();
    matrix = new int[(mp->inputNum)*MAXCYCLE];
    
    ifstream fileHandle;
	fileHandle.open(vector.c_str(), ifstream::in);
	if(!fileHandle.is_open()){
		perror("there is no vector file for logic simulation");
		exit(1);
	}

    for(int i = 0; i < MAXCYCLE; i++){
        for(int j = 0; j < mp->inputNum; j++){
            fileHandle>>matrix[i*(mp->inputNum)+j];
        }
    }
    fileHandle.close();
    
    for(int i = 0; i < MAXCYCLE; i++){
		switch(option){
			case 0: elabLogicSim(i); break;
			case 1: partitionLogicSim(i); break;
//        cout<<"cycle "<<i<<" is complete"<<endl;
		}
    }
    
    return 0;
}

int simpleLogicSim(){
    
    map<Node*, Node*>::iterator it;
    module* mp;
    
    /*
    for(int i = 0; i < inputCount; i++){
        nodeInput[i]->logic = ZERO;
    }
    **/
    
    for(unsigned int i = 0; i < moduleAll.size(); i++){
        mp = moduleAll[i];
        for(it = mp->ffMap.begin(); it != mp->ffMap.end(); it++){
            (*it).second->logic = ZERO;
        }
    }
    
    for(int i = 1; i <= maxLevel; i++){
        for(int j = 0; j < allCount; j++){
            if(nodeAll[j]->level == i){
                nodeAll[j]->logic = (LType)nodeLogic(nodeAll[j]);
            }
        }
    }
    
    return 0;
}

//unit testing for 24-bit multiplier netlist
int logicSimTest(int a, int b){
    
    long long result = 0;
    int temp;
    int tempa = a;
    int tempb = b;
    time_t start, end;
    double diff;
    
    for(int i = 0; i < 24; i++){
        temp = a & 1;
        if(temp == 0){
            nodeInput[i]->logic = ZERO;
        }else{
            nodeInput[i]->logic = ONE;
        }
        a = a >> 1;
    }
    
    for(int i = 24; i < 48; i++){
        temp = b & 1;
        if(temp == 0){
            nodeInput[i]->logic = ZERO;
        }else{
            nodeInput[i]->logic = ONE;
        }
        b = b >> 1;
    }
    
    time(&start);
    simpleLogicSim();
    time(&end);
    diff = difftime(end, start);
    
    for(int i = 47; i >= 0; i--){
        if(nodeOutput[i]->logic == ZERO){
            result = result & 0xfffffffffffffffeLL;
        }else if(nodeOutput[i]->logic == ONE){
            result = result | 1;
        }
        result = result << 1;
    }
    
    cout<<tempa<<" * "<<tempb<<" = "<<result<<endl;
    printf("CPU took %.5f seconds to do logic simulation\n", diff);
    
    return 0;
}

void modInsertInput(module* modPtr, string name, Node* np){
    
    map<string, vector<Node*> >::iterator it = modPtr->inputMap.find(name);
    if(it != modPtr->inputMap.end()){
        (*it).second.push_back(np);
    }else{
        vector<Node*> temp;
        temp.push_back(np);
        modPtr->inputMap.insert(pair<string, vector<Node*> >(name, temp));
    }
}

void modInsertOutput(module* modPtr, string name, Node* np){
    
    map<string, vector<Node*> >::iterator it = modPtr->outputMap.find(name);
    if(it != modPtr->outputMap.end()){
        (*it).second.push_back(np);
    }else{
        vector<Node*> temp;
        temp.push_back(np);
        modPtr->outputMap.insert(pair<string, vector<Node*> >(name, temp));
    }
}

void modInsertWire(module* modPtr, string name, Node* np){
    
    map<string, vector<Node*> >::iterator it = modPtr->wireMap.find(name);
    if(it != modPtr->wireMap.end()){
        (*it).second.push_back(np);
    }else{
        vector<Node*> temp;
        temp.push_back(np);
        modPtr->wireMap.insert(pair<string, vector<Node*> >(name, temp));
    }
}

//process 1'b1 or 5'b11110
int constNode(string value, Node* np){
    vector<string> splitResult;
    int wid;
    
//    cout<<value<<endl;
    boost::split(splitResult, value, boost::is_any_of("'"));
    
    if((wid = atoi(splitResult[0].c_str())) == 1){
        switch (splitResult[1].at(wid)){
            case '1': np->logic = ONE; break;
            case '0': np->logic = ZERO; break;
        }
    }
    
    return 0;
}

void prepareVector(){
    
    module* mp = moduleAll.back();
    ofstream fileHandle;
	fileHandle.open("vector.txt", ofstream::out);
    
    //initialize the random seed
    srand(time(NULL));
    for(int i = 0; i < MAXCYCLE; i++){
        for(int j = 0; j < mp->inputNum; j++){
            fileHandle<<rand()%2<<" ";
        }
        fileHandle<<endl;
    }
    
    fileHandle.close();
}

/*
 * 
 */
int processModule(string netlist) {
    
    ifstream fileHandle;
    ofstream fileTemp;
    int filePos;
    char buffer[MAXLINE*200];
    char keyword[MAXLINE/2];
    char modName[MAXLINE/2];
    char nodeNameL[MAXLINE/2];
    char nodeNameR[MAXLINE/2];
    
    string pattern;
    boost::sregex_iterator end;
    
    int min, max, mIndex, width;
    Node* nodePtr, *np;
    string name, line, subname;
    
    vector<string> splitResult;
    
    Node* nodeA, *nodeB, *nodeC, *nodeD;
    Node* nodeY, *nodeYC, *nodeYS;
    Node* nodeQ, *nodeS;
    
    int inputNum = 0;
    KWord state;
    
    module* modPtr, *mMatchPtr;
    bool flag;
    map<string, vector<Node*> >::iterator mit;
    map<string, vector<Node*> >::iterator mjt;
	int modIndex;
    
    //initialize the global variables
    initGlobal();
    
    //open verilog file
	fileHandle.open(netlist.c_str(), ifstream::in);
	if(!fileHandle.is_open()) exit(1);

	netlist.replace(netlist.find('.')+1, 3, "mod");  
	fileTemp.open(netlist.c_str(), ofstream::out);
    
    while(!fileHandle.eof()){
        fileHandle.getline(buffer, MAXLINE*10);
        line = string(buffer);
        if(!line.compare("endmodule")){
            line.append(";");
        }
        line.append("\n");
        fileTemp.write(line.c_str(), line.length());
    }
    fileHandle.close();
    fileTemp.close();
    
	fileHandle.open(netlist.c_str(), fstream::in);
    while(!fileHandle.eof()){
        
        allCount = 0;
        inputCount = 0;
        outputCount = 0;
        wireCount = 0;
        
        //read verilog file for the first time
        cout<<"readin the verilog for the first time"<<endl;
        flag = true;
        filePos = fileHandle.tellg();
        
        while(flag && !fileHandle.getline(buffer, MAXLINE*200, ';').eof()){
            line = string(buffer) + string(";");
            if(sscanf(buffer, "%s", keyword) == 1){
                string key(keyword);
//                cout<<key<<endl;
                if(kIsDefined(key) != -1){
                    if(!key.compare("module")){
                        BOOST_ASSERT(sscanf(buffer, "%s %s", keyword, modName) == 2);
                        modPtr = new module(string(modName));
						modIndex = moduleAll.size();
                        moduleAll.push_back(modPtr);
                        cout<<"module "<<modName<<" is parsed"<<endl;
                    }else if(!key.compare("endmodule")){
                        flag = false;
                    }else if(!key.compare("wire")){ //scan wire line
                        cout<<"scan wire variable:"<<endl;
                        state = WIRE;
                        pattern = string("\\[[0-9]+:[0-9]+\\]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                name = it->str();
                                cout<<name<<endl;
                                if(sscanf(name.c_str(), "[%d:%d]", &max, &min) == 2){ //wire is bus
                                    wireCount = (max > min)?(wireCount + max - min + 1) : (wireCount + min - max + 1);
                                }
                                break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
//                                cout<<it->str()<<" ";
                                wireCount++;
                            }
//                            cout<<endl;
                        }
                    }else if(!key.compare("output")){ //scan output line
                        cout<<"scan output variable:"<<endl;
                        state = OUTPUT;
                        pattern = string("\\[[0-9]+:[0-9]+\\]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<endl;
                                name = it->str();
                                if(sscanf(name.c_str(), "[%d:%d]", &max, &min) == 2){ //output is bus
                                    outputCount = (max > min)?(outputCount + max - min + 1):(outputCount + min - max + 1);
                                }
                                break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<" ";
                                outputCount++;
                            }
                            cout<<endl;
                        }
                    }else if(!key.compare("input")){ //scan input line
                        cout<<"scan input variable:"<<endl;
                        state = INPUT;
                        pattern = string("\\[[0-9]+:[0-9]+\\]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<endl;
                                name = it->str();
                                if(sscanf(name.c_str(), "[%d:%d]", &max, &min) == 2){ //input is bus
                                    inputCount = (max > min)?(inputCount + max - min + 1):(inputCount + min - max + 1);
                                }
                                break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<" ";
                                inputCount++;
                            }
                            cout<<endl;
                        }
                    }
                }else if(gIsDefined(key) == -1 && mIsDefined(key) == -1){
                    pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                    boost::regex regex(pattern.c_str());
                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                    for(; it != end; it++){
                        cout<<it->str()<<" ";
                        switch (state){
                            case INPUT: inputCount++; break;
                            case OUTPUT: outputCount++; break;
                            case WIRE: wireCount++; break;
                        }
                    }
                    cout<<endl;
                }
            }
        }

        if(!fileHandle.eof()){
            cout<<"number of wire: "<<wireCount<<endl;
            cout<<"number of output: "<<outputCount<<endl;
            cout<<"number of input: "<<inputCount<<endl;
            nodeAll = new Node* [inputCount + wireCount + outputCount];
            nodeInput = new Node* [inputCount];
            nodeOutput = new Node* [outputCount];

            modPtr->nAll = nodeAll;
            modPtr->nInput = nodeInput;
            modPtr->nOutput = nodeOutput;
            modPtr->allNum = inputCount + wireCount + outputCount;
            modPtr->inputNum = inputCount;
            modPtr->outputNum = outputCount;
            
            inputCount = 0;
            outputCount = 0;
        }
        
        flag = true;

        //read the verilog for the second time
        cout<<"readin the verilog for the second time"<<endl;
        fileHandle.seekg(filePos);
        while(flag && !fileHandle.getline(buffer, MAXLINE*200, ';').eof()){
            line = string(buffer) + string(";");
            if(sscanf(buffer, "%s", keyword) == 1){
                string key(keyword);
                if(kIsDefined(key) != -1){
                    if(!key.compare("endmodule")){
                        flag = false;
                    }else if(!key.compare("wire")){ //scan wire line
                        state = WIRE;
                        pattern = string("\\[[0-9]+:[0-9]+\\]\\s[a-zA-Z0-9_]+[,;]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<endl;
                                name = it->str();
                                boost::split(splitResult, name, boost::is_any_of(" "));
                                boost::trim_right_if(splitResult[1], boost::is_any_of(",;"));
                                if(sscanf(splitResult[0].c_str(), "[%d:%d]", &max, &min) == 2){ //wire is bus
                                    int tempMax = (max > min)?max:min;
                                    for(int i = (max > min)?min:max; i <= tempMax; i++){
                                        string newName = splitResult[1] + "[" + 
                                            boost::lexical_cast<string>(i) + "]";
										nodePtr = new Node(modIndex, allCount, newName, GATE, i);
                                        nodeAll[allCount++] = nodePtr;
                                        modInsertWire(modPtr, splitResult[1], nodePtr);
                                    }
                                }
                            break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
//                                cout<<it->str()<<" ";
                                name = it->str();
                                boost::trim_right_if(name, boost::is_any_of(",;"));
								nodePtr = new Node(modIndex, allCount, name, GATE, 0);
                                nodeAll[allCount++] = nodePtr;
                                modInsertWire(modPtr, name, nodePtr);
                            }
//                            cout<<endl;
                        }
                    }else if(!key.compare("output")){ //scan output line
                        state = OUTPUT;
                        pattern = string("\\[[0-9]+:[0-9]+\\]\\s[a-zA-Z0-9_]+[,;]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<endl;
                                name = it->str();
                                boost::split(splitResult, name, boost::is_any_of(" "));
                                boost::trim_right_if(splitResult[1], boost::is_any_of(",;"));
                                if(sscanf(splitResult[0].c_str(), "[%d:%d]", &max, &min) == 2){ //output is bus
                                    int tempMax = (max > min)?max:min;
                                    for(int i = (max > min)?min:max; i <= tempMax; i++){
                                        string newName = splitResult[1] + "[" + 
                                            boost::lexical_cast<string>(i) + "]";
										nodePtr = new Node(modIndex, allCount, newName, PO, i);
                                        nodeAll[allCount++] = nodePtr;
                                        nodeOutput[outputCount++] = nodePtr;
                                        modInsertOutput(modPtr, splitResult[1], nodePtr);
                                    }
                                }
                            break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                name = it->str();
                                cout<<name<<" ";
                                boost::trim_right_if(name, boost::is_any_of(",;"));
								nodePtr = new Node(modIndex, allCount, name, PO, 0);
                                nodeAll[allCount++] = nodePtr;
                                nodeOutput[outputCount++] = nodePtr;
                                modInsertOutput(modPtr, name, nodePtr);
                            }
                            cout<<endl;
                        }
                    }else if(!key.compare("input")){ //scan input line
                        state = INPUT;
                        pattern = string("\\[[0-9]+:[0-9]+\\]\\s[a-zA-Z0-9_]+[,;]");
                        boost::regex regex(pattern.c_str());
                        if(boost::regex_search(line.begin(), line.end(), regex)){
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                cout<<it->str()<<endl;
                                name = it->str();
                                boost::split(splitResult, name, boost::is_any_of(" "));
                                boost::trim_right_if(splitResult[1], boost::is_any_of(",;"));
                                if(sscanf(splitResult[0].c_str(), "[%d:%d]", &max, &min) == 2){
                                    int tempMax = (max > min)?max:min;
                                    for(int i = (max > min)?min:max; i <= tempMax; i++){
                                        string newName = splitResult[1] + "[" + 
                                            boost::lexical_cast<string>(i) + "]";
										nodePtr = new Node(modIndex, allCount, newName, PI, i);
                                        nodePtr->gate = IPT;
                                        nodeAll[allCount++] = nodePtr;
                                        nodeInput[inputCount++] = nodePtr;
                                        modInsertInput(modPtr, splitResult[1], nodePtr);
                                    }
                                }
                            break;
                            }
                        }else{
                            pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                            boost::regex regex(pattern.c_str());
                            boost::sregex_iterator it(line.begin(), line.end(), regex);
                            for(; it != end; it++){
                                name = it->str();
                                cout<<name<<" ";
                                boost::trim_right_if(name, boost::is_any_of(",;"));
								nodePtr = new Node(modIndex, allCount, name, PI, 0);
                                nodePtr->gate = IPT;
                                nodeAll[allCount++] = nodePtr;
                                nodeInput[inputCount++] = nodePtr;
                                modInsertInput(modPtr, name, nodePtr);
                            }
                            cout<<endl;
                        }
                    }
                }else if(gIsDefined(key) == -1 && mIsDefined(key) == -1){
                    pattern = string("\\b[a-zA-Z0-9_]+[,;]");
                    boost::regex regex(pattern.c_str());
                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                    for(; it != end; it++){
                        name = it->str();
                        boost::trim_right_if(name, boost::is_any_of(",;"));
                        switch (state){
							case INPUT: nodePtr = new Node(modIndex, allCount, name, PI, 0); break;
							case OUTPUT: nodePtr = new Node(modIndex, allCount, name, PO, 0); break;
							case WIRE: nodePtr = new Node(modIndex, allCount, name, GATE, 0); break;
                        }
                        nodeAll[allCount++] = nodePtr;
                    }
                }
            }
        }

        //read the verilog for the third time
        cout<<"readin the verilog for the third time"<<endl;
        flag = true;
        fileHandle.seekg(filePos);
        while(flag && !fileHandle.getline(buffer, MAXLINE*200, ';').eof()){
            line = string(buffer) + string(";");
            if(sscanf(buffer, "%s", keyword) == 1){
                string key(keyword);
//                cout<<key<<endl;
                if(!key.compare("endmodule")){
                    flag = false;
                }else if(!key.compare("assign")){
                    BOOST_ASSERT(sscanf(buffer, "%s %s = %s", keyword, nodeNameL, nodeNameR) == 3);
                    nodeY = nodeAll[findNode(string(nodeNameL))];
                    name = string(nodeNameR);
                    boost::trim_right_if(name, boost::is_any_of(",;)"));
                    int nIndex = findNode(name);
                    if(nIndex != -1){
                        nodeA = nodeAll[findNode(name)];
                    }else{
						nodeA = new Node(modIndex, -1, string("dummy"), DUMMY, 0);
                        constNode(name, nodeA);
                        modPtr->nFloat.push_back(nodeA);
                    }
                    (nodeA->fanout)++;
                    nodeA->downNodes.push_back(nodeY);
                    nodeY->fanin = 1;
                    nodeY->upperNodes.push_back(nodeA);
                    nodeY->gate = BUFX2;
                }else if(gIsDefined(key) != -1){
                    if(!key.compare("INVX1") || !key.compare("INVX2")
                            || !key.compare("INVX4") || !key.compare("INVX8")
                            || !key.compare("BUFX2") || !key.compare("BUFX4")){
                        pattern = string("\\.A\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexA(pattern.c_str());
                        boost::sregex_iterator itA(line.begin(), line.end(), regexA);
                        for(; itA != end; itA++){
                            name = itA->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeA = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.Y\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexY(pattern.c_str());
                        boost::sregex_iterator itY(line.begin(), line.end(), regexY);
                        for(; itY != end; itY++){
                            name = itY->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeY = nodeAll[findNode(name)];
                            break;
                        }
                        (nodeA->fanout)++;
                        nodeA->downNodes.push_back(nodeY);
                        nodeY->fanin = 1;
                        nodeY->upperNodes.push_back(nodeA);
                        if(!key.compare("INVX1")){
                            nodeY->gate = INVX1;
                        }else if(!key.compare("INVX2")){
                            nodeY->gate = INVX2;
                        }else if(!key.compare("INVX4")){
                            nodeY->gate = INVX4;
                        }else if(!key.compare("INVX8")){
                            nodeY->gate = INVX8;
                        }else if(!key.compare("BUFX2")){
                            nodeY->gate = BUFX2;
                        }else if(key.compare("BUFX4")){
                            nodeY->gate = BUFX4;
                        }
                    }else if(!key.compare("DFFPOSX1") || !key.compare("DFFNEGX1") || !key.compare("DFFSR")){
                        pattern = string("\\.D\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexD(pattern.c_str());
                        boost::sregex_iterator itD(line.begin(), line.end(), regexD);
                        for(; itD != end; itD++){
                            name = itD->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeD = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.Q\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexQ(pattern.c_str());
                        boost::sregex_iterator itQ(line.begin(), line.end(), regexQ);
                        for(; itQ != end; itQ++){
                            name = itQ->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeQ = nodeAll[findNode(name)];
                            break;
                        }
                        nodeD->fanout = 0;
                        nodeD->type = PPO;
                        nodeQ->fanin = 0;
                        nodeQ->type = PPI;
                        nodeQ->gate = IPT;
                        modPtr->ffMap.insert(pair<Node*, Node*>(nodeD, nodeQ)); //map for flip flop
                        
                    }else if(!key.compare("HAX1") || !key.compare("FAX1")){
                        pattern = string("\\.A\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexA(pattern.c_str());
                        boost::sregex_iterator itA(line.begin(), line.end(), regexA);
                        for(; itA != end; itA++){
                            name = itA->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeA = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.B\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexB(pattern.c_str());
                        boost::sregex_iterator itB(line.begin(), line.end(), regexB);
                        for(; itB != end; itB++){
                            name = itB->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeB = nodeAll[findNode(name)];
                            break;
                        }
                        if(!key.compare("FAX1")){
                            pattern = string("\\.C\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                            boost::regex regexC(pattern.c_str());
                            boost::sregex_iterator itC(line.begin(), line.end(), regexC);
                            for(; itC != end; itC++){
                                name = itC->str();
                                boost::trim_right_if(name, boost::is_any_of(",;)"));
                                name.erase(0, 3);
                                boost::trim_left_if(name, boost::is_any_of(" \n"));
                                nodeC = nodeAll[findNode(name)];
                                break;
                            } 
                        }
                        pattern = string("\\.YC\\([a-zA-Z0-9_\\[\\]\\s]*\\)");
                        boost::regex regexYC(pattern.c_str());
                        boost::sregex_iterator itYC(line.begin(), line.end(), regexYC);
                        for(; itYC != end; itYC++){
                            name = itYC->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 4);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            if(name.length() > 0){
                                nodeYC = nodeAll[findNode(name)];
                            }else{
								nodeYC = new Node(modIndex, -1, string("dummy"), DUMMY, 0); //output dummy node
                            }
                            break;
                        }
                        pattern = string("\\.YS\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexYS(pattern.c_str());
                        boost::sregex_iterator itYS(line.begin(), line.end(), regexYS);
                        for(; itYS != end; itYS++){
                            name = itYS->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 4);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeYS = nodeAll[findNode(name)];
                            break;
                        }
                        nodeA->fanout = nodeA->fanout + 2;
                        nodeA->downNodes.push_back(nodeYC);
                        nodeA->downNodes.push_back(nodeYS);
                        nodeB->fanout = nodeB->fanout + 2;
                        nodeB->downNodes.push_back(nodeYC);
                        nodeB->downNodes.push_back(nodeYS);
                        if(!key.compare("HAX1")){
                            nodeYC->fanin = 2;
                            nodeYC->upperNodes.push_back(nodeB);
                            nodeYC->upperNodes.push_back(nodeA);
                            nodeYC->gate = HAC;
                            nodeYS->fanin = 2;
                            nodeYS->upperNodes.push_back(nodeB);
                            nodeYS->upperNodes.push_back(nodeA);
                            nodeYS->gate = HAS;
                        }else{
                            nodeC->fanout = nodeC->fanout + 2;
                            nodeC->downNodes.push_back(nodeYC);
                            nodeC->downNodes.push_back(nodeYS);
                            nodeYC->fanin = 3;
                            nodeYC->upperNodes.push_back(nodeC);
                            nodeYC->upperNodes.push_back(nodeB);
                            nodeYC->upperNodes.push_back(nodeA);
                            nodeYC->gate = FAC;
                            nodeYS->fanin = 3;
                            nodeYS->upperNodes.push_back(nodeC);
                            nodeYS->upperNodes.push_back(nodeB);
                            nodeYS->upperNodes.push_back(nodeA);
                            nodeYS->gate = FAS;
                        }
                    }else if(!key.compare("MUX2X1")){
                        pattern = string("\\.A\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexA(pattern.c_str());
                        boost::sregex_iterator itA(line.begin(), line.end(), regexA);
                        for(; itA != end; itA++){
                            name = itA->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeA = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.B\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexB(pattern.c_str());
                        boost::sregex_iterator itB(line.begin(), line.end(), regexB);
                        for(; itB != end; itB++){
                            name = itB->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeB = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.S\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexS(pattern.c_str());
                        boost::sregex_iterator itS(line.begin(), line.end(), regexS);
                        for(; itS != end; itS++){
                            name = itS->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeS = nodeAll[findNode(name)];
                            break;
                        }
                        pattern = string("\\.Y\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexY(pattern.c_str());
                        boost::sregex_iterator itY(line.begin(), line.end(), regexY);
                        for(; itY != end; itY++){
                            name = itY->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeY = nodeAll[findNode(name)];
                            break;
                        }
                        (nodeA->fanout)++;
                        nodeA->downNodes.push_back(nodeY);
                        (nodeB->fanout)++;
                        nodeB->downNodes.push_back(nodeY);
                        (nodeS->fanout)++;
                        nodeS->downNodes.push_back(nodeY);
                        nodeY->fanin = 3;
                        nodeY->upperNodes.push_back(nodeS);
                        nodeY->upperNodes.push_back(nodeB);
                        nodeY->upperNodes.push_back(nodeA);
                        nodeY->gate = MUX2X1;
                    }else{
                        pattern = string("[0-9]+X");
                        boost::regex regex(pattern.c_str());
                        boost::sregex_iterator it(line.begin(), line.end(), regex);
                        for(; it != end; it++){
                            name = it->str();
                            if(name.length() == 2){
                                inputNum = atoi(name.substr(0, 1).c_str());
                            }else if(name.length() == 3){
                                inputNum = atoi(name.substr(0, 1).c_str()) + 
                                        atoi(name.substr(1, 1).c_str());
                            }else{
                                cout<<"gate type has error"<<endl;
                            }
                            break;
                        }
                        for(int i = inputNum; i > 0; i--){
                            switch (i){
                                case 1:
                                {
                                    pattern = string("\\.A\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                                    boost::regex regex(pattern.c_str());
                                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                                    for(; it != end; it++){
                                        name = it->str();
                                        boost::trim_right_if(name, boost::is_any_of(",;)"));
                                        name.erase(0, 3);
                                        boost::trim_left_if(name, boost::is_any_of(" \n"));
                                        nodeA = nodeAll[findNode(name)];
                                        break;
                                    }
                                    break;
                                }
                                case 2:
                                {
                                    pattern = string("\\.B\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                                    boost::regex regex(pattern.c_str());
                                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                                    for(; it != end; it++){
                                        name = it->str();
                                        boost::trim_right_if(name, boost::is_any_of(",;)"));
                                        name.erase(0, 3);
                                        boost::trim_left_if(name, boost::is_any_of(" \n"));
                                        nodeB = nodeAll[findNode(name)];
                                        break;
                                    }
                                    break;
                                }
                                case 3:
                                {
                                    pattern = string("\\.C\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                                    boost::regex regex(pattern.c_str());
                                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                                    for(; it != end; it++){
                                        name = it->str();
                                        boost::trim_right_if(name, boost::is_any_of(",;)"));
                                        name.erase(0, 3);
                                        boost::trim_left_if(name, boost::is_any_of(" \n"));
                                        nodeC = nodeAll[findNode(name)];
                                        break;
                                    }
                                    break;
                                }
                                case 4:
                                {
                                    pattern = string("\\.D\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                                    boost::regex regex(pattern.c_str());
                                    boost::sregex_iterator it(line.begin(), line.end(), regex);
                                    for(; it != end; it++){
                                        name = it->str();
                                        boost::trim_right_if(name, boost::is_any_of(",;)"));
                                        name.erase(0, 3);
                                        boost::trim_left_if(name, boost::is_any_of(" \n"));
                                        nodeD = nodeAll[findNode(name)];
                                        break;
                                    }
                                    break;
                                }
                            }
                        }
                        pattern = string("\\.Y\\([a-zA-Z0-9_\\[\\]\\s]+\\)");
                        boost::regex regexY(pattern.c_str());
                        boost::sregex_iterator itY(line.begin(), line.end(), regexY);
                        for(; itY != end; itY++){
                            name = itY->str();
                            boost::trim_right_if(name, boost::is_any_of(",;)"));
                            name.erase(0, 3);
                            boost::trim_left_if(name, boost::is_any_of(" \n"));
                            nodeY = nodeAll[findNode(name)];
                            break;
                        }
                        for(int i = inputNum; i > 0; i--){
                            switch (i){
                                case 1:
                                {
                                    (nodeA->fanout)++;
                                    nodeA->downNodes.push_back(nodeY);
                                    nodeY->upperNodes.push_back(nodeA);
                                    break;
                                }
                                case 2:
                                {
                                    (nodeB->fanout)++;
                                    nodeB->downNodes.push_back(nodeY);
                                    nodeY->upperNodes.push_back(nodeB);
                                    break;
                                }
                                case 3:
                                {
                                    (nodeC->fanout)++;
                                    nodeC->downNodes.push_back(nodeY);
                                    nodeY->upperNodes.push_back(nodeC);
                                    break;
                                }
                                case 4:
                                {
                                    (nodeD->fanout)++;
                                    nodeD->downNodes.push_back(nodeY);
                                    nodeY->upperNodes.push_back(nodeD);
                                    break;
                                }
                            }
                        }
                        nodeY->fanin = inputNum;
                        nodeY->gate = (GType)(gIsDefined(key));
                    }
                }else if((mIndex = mIsDefined(key)) != -1){ //mit is lower level while mjt is higher level
                    mMatchPtr = moduleAll[mIndex];
                    for(mit = mMatchPtr->inputMap.begin(); mit != mMatchPtr->inputMap.end(); mit++){
                        pattern = string("\\.") + (*mit).first + string("\\([\\{\\}\\s,'a-zA-Z0-9_\\[\\]:]+\\)");
                        boost::regex regexM(pattern.c_str());
                        boost::sregex_iterator itM(line.begin(), line.end(), regexM);
                        for(; itM != end; itM++){
                            name = itM->str();
//                            cout<<name<<endl;
                            if((*mit).second.size() > 1){ //input of submodule is bus
                                if(name.find('{', 0) != string::npos){ //if bus is grouped
                                    pattern = string("[\\[\\]:'a-zA-Z0-9_]+[,;}]");
                                    boost::regex regexW(pattern.c_str());
                                    boost::sregex_iterator itW(name.begin(), name.end(), regexW);
                                    width = (*mit).second.size();
                                    for(; itW != end; itW++){
                                        subname = itW->str();
                                        boost::trim_right_if(subname, boost::is_any_of(",;)}"));
                                        boost::split(splitResult, subname, boost::is_any_of("["));
                                        mjt = modPtr->inputMap.find(splitResult[0]);
                                        if(mjt == modPtr->inputMap.end()){
                                            mjt = modPtr->wireMap.find(splitResult[0]);
                                            if(mjt == modPtr->wireMap.end()){
                                                mjt = modPtr->outputMap.find(splitResult[0]);
                                                if(mjt == modPtr->outputMap.end()){
													np = new Node(modIndex, -1, string("dummy"), DUMMY, 0);
                                                    constNode(splitResult[0], np);
                                                    modPtr->nFloat.push_back(np);
                                                    (np->fanout)++;
                                                    np->downNodes.push_back((*mit).second[width-1]);
                                                    (*mit).second[width-1]->fanin = 1;
                                                    (*mit).second[width-1]->upperNodes.push_back(np);
                                                    (*mit).second[width-1]->gate = BUFX2;
                                                    width--;
                                                    continue;
                                                }
                                            }
                                        }

                                        if((*mjt).second.size() > 1){ //input of top module is bus
                                            if(splitResult.size() > 1){ //subbus is used
                                                if(sscanf(splitResult[1].c_str(), "%d:%d", &max, &min) == 2){
                                                    if(max < min) swap(max, min);
                                                    for(int k = min - (*mjt).second[0]->busIndex; 
                                                            k <= max - (*mjt).second[0]->busIndex; k++){
                                                        np = (*mjt).second[k];
                                                        (np->fanout)++;
                                                        int temp = width-max+min-1+k-min+(*mjt).second[0]->busIndex;
                                                        np->downNodes.push_back((*mit).second[temp]);
                                                        (*mit).second[temp]->fanin = 1;
                                                        (*mit).second[temp]->upperNodes.push_back(np);
                                                        (*mit).second[temp]->gate = BUFX2;
                                                    }
                                                    width = width - (max - min + 1);
                                                }else{ //only one line of bus is used
                                                    BOOST_ASSERT(sscanf(splitResult[1].c_str(), "%d", &max) == 1);
                                                    np = (*mjt).second[max-(*mjt).second[0]->busIndex];
                                                    (np->fanout)++;
                                                    np->downNodes.push_back((*mit).second[width-1]);
                                                    (*mit).second[width-1]->fanin = 1;
                                                    (*mit).second[width-1]->upperNodes.push_back(np);
                                                    (*mit).second[width-1]->gate = BUFX2;
                                                    width--;
                                                }
                                            }else{ //all line in bus is used
                                                for(int k = 0; k < (*mjt).second.size(); k++){
                                                    np = (*mjt).second[k];
                                                    (np->fanout)++;
                                                    np->downNodes.push_back((*mit).second[width-(*mjt).second.size()+k]);
                                                    (*mit).second[width-(*mjt).second.size()+k]->fanin = 1;
                                                    (*mit).second[width-(*mjt).second.size()+k]->upperNodes.push_back(np);
                                                    (*mit).second[width-(*mjt).second.size()+k]->gate = BUFX2;
                                                }
                                                width = width - (*mjt).second.size();
                                            }
                                        }else{ //input of top module is a line
                                            np = (*mjt).second[0];
                                            (np->fanout)++;
                                            np->downNodes.push_back((*mit).second[width-1]);
                                            (*mit).second[width-1]->fanin = 1;
                                            (*mit).second[width-1]->upperNodes.push_back(np);
                                            (*mit).second[width-1]->gate = BUFX2;
                                            width--;
                                        }
                                    }
                                }else{ //bus is not grouped
                                    boost::trim_right_if(name, boost::is_any_of(",;)"));
                                    name.erase(0, (*mit).first.length()+2);
                                    boost::trim_left_if(name, boost::is_any_of(" \n"));
                                    boost::split(splitResult, name, boost::is_any_of("["));
                                    mjt = modPtr->inputMap.find(splitResult[0]);
                                    if(mjt == modPtr->inputMap.end()){
                                        mjt = modPtr->wireMap.find(splitResult[0]);
                                        if(mjt == modPtr->wireMap.end()){
                                            mjt = modPtr->outputMap.find(splitResult[0]);
                                        }
                                    }
                                    
                                    if(splitResult.size() > 1){ //sub bus is used
                                        BOOST_ASSERT(sscanf(splitResult[1].c_str(), "%d:%d", &max, &min) == 2);
                                        if(max < min) swap(max, min);
                                        for(int k = min - (*mjt).second[0]->busIndex; 
                                                k <= max - (*mjt).second[0]->busIndex; k++){
                                            np = (*mjt).second[k];
                                            (np->fanout)++;
                                            int temp = k - min + (*mjt).second[0]->busIndex;
                                            np->downNodes.push_back((*mit).second[temp]);
                                            (*mit).second[temp]->fanin = 1;
                                            (*mit).second[temp]->upperNodes.push_back(np);
                                            (*mit).second[temp]->gate = BUFX2;
                                        }
                                    }else{ //all line in bus is used
                                        for(int k = 0; k < (*mjt).second.size(); k++){
                                            np = (*mjt).second[k];
                                            (np->fanout)++;
                                            np->downNodes.push_back((*mit).second[k]);
                                            (*mit).second[k]->fanin = 1;
                                            (*mit).second[k]->upperNodes.push_back(np);
                                            (*mit).second[k]->gate = BUFX2;
                                        }
                                    }
                                }
                            }else{ //input of submodule is a line
                                boost::trim_right_if(name, boost::is_any_of(",;)"));
                                name.erase(0, (*mit).first.length()+2);
                                boost::trim_left_if(name, boost::is_any_of(" \n"));
                                int nIndex = findNode(name);
                                if(nIndex != -1){
                                    np = nodeAll[nIndex];
                                }else{
									np = new Node(modIndex, -1, string("dummy"), DUMMY, 0);
                                    constNode(name, np);
                                    modPtr->nFloat.push_back(np);
                                }
                                (np->fanout)++;
                                np->downNodes.push_back((*mit).second[0]);
                                (*mit).second[0]->fanin = 1;
                                (*mit).second[0]->upperNodes.push_back(np);
                                (*mit).second[0]->gate = BUFX2;
                            }
                                       
                            break;
                        }
                    }
                
                    for(mit = mMatchPtr->outputMap.begin(); mit != mMatchPtr->outputMap.end(); mit++){
                        pattern = string("\\.") + (*mit).first + string("\\([\\{\\}\\s,a-zA-Z0-9_\\[\\]:]+\\)");
                        boost::regex regexM(pattern.c_str());
                        boost::sregex_iterator itM(line.begin(), line.end(), regexM);
                        for(; itM != end; itM++){
                            name = itM->str();
//                            cout<<name<<endl;
                            if((*mit).second.size() > 1){ //output of submodule is bus
                                if(name.find('{', 0) != string::npos){
                                    pattern = string("[\\[\\]:a-zA-Z0-9_]+[,;}]");
                                    boost::regex regexW(pattern.c_str());
                                    boost::sregex_iterator itW(name.begin(), name.end(), regexW);
                                    width = (*mit).second.size();
                                    for(; itW != end; itW++){
                                        subname = itW->str();
                                        boost::trim_right_if(subname, boost::is_any_of(",;)}"));
                                        boost::split(splitResult, subname, boost::is_any_of("["));
                                        mjt = modPtr->outputMap.find(splitResult[0]);
                                        if(mjt == modPtr->outputMap.end()){
                                            mjt = modPtr->wireMap.find(splitResult[0]);
                                        }

                                        if((*mjt).second.size() > 1){
                                            if(splitResult.size() > 1){
                                                if(sscanf(splitResult[1].c_str(), "%d:%d", &max, &min) == 2){
                                                    if(max < min) swap(max, min);
                                                    for(int k = min - (*mjt).second[0]->busIndex; 
                                                            k <= max - (*mjt).second[0]->busIndex; k++){
                                                        np = (*mjt).second[k];
                                                        int temp = width-max+min-1+k-min+(*mjt).second[0]->busIndex;
                                                        ((*mit).second[temp]->fanout)++;
                                                        (*mit).second[temp]->downNodes.push_back(np);
                                                        np->fanin = 1;
                                                        np->upperNodes.push_back((*mit).second[temp]);
                                                        np->gate = BUFX2;
                                                    }
                                                    width = width - (max - min + 1);
                                                }else{
                                                    BOOST_ASSERT(sscanf(splitResult[1].c_str(), "%d", &max) == 1);
                                                    np = (*mjt).second[max-(*mjt).second[0]->busIndex];
                                                    ((*mit).second[width-1]->fanout)++;
                                                    (*mit).second[width-1]->downNodes.push_back(np);
                                                    np->fanin = 1;
                                                    np->upperNodes.push_back((*mit).second[width-1]);
                                                    np->gate = BUFX2;
                                                    width--;
                                                }
                                            }else{
                                                for(unsigned int k = 0; k < (*mjt).second.size(); k++){
                                                    np = (*mjt).second[k];
                                                    ((*mit).second[width-(*mjt).second.size()+k]->fanout)++;
                                                    (*mit).second[width-(*mjt).second.size()+k]->downNodes.push_back(np);
                                                    np->fanin = 1;
                                                    np->upperNodes.push_back((*mit).second[width-(*mjt).second.size()+k]);
                                                    np->gate = BUFX2;
                                                }
                                                width = width - (*mjt).second.size();
                                            }
                                        }else{
                                            np = (*mjt).second[0];
                                            ((*mit).second[width-1]->fanout)++;
                                            (*mit).second[width-1]->downNodes.push_back(np);
                                            np->fanin = 1;
                                            np->upperNodes.push_back((*mit).second[width-1]);
                                            np->gate = BUFX2;
                                            width--;
                                        }
                                    }
                                }else{
                                    boost::trim_right_if(name, boost::is_any_of(",;)"));
                                    name.erase(0, (*mit).first.length()+2);
                                    boost::trim_left_if(name, boost::is_any_of(" \n"));
                                    boost::split(splitResult, name, boost::is_any_of("["));
                                    mjt = modPtr->outputMap.find(splitResult[0]);
                                    if(mjt == modPtr->outputMap.end()){
                                        mjt = modPtr->wireMap.find(name);
                                    }
                                    if(splitResult.size() > 1){
                                        BOOST_ASSERT(sscanf(splitResult[1].c_str(), "%d:%d", &max, &min) == 2);
                                        if(max < min) swap(max, min);
                                        for(int k = min - (*mjt).second[0]->busIndex; 
                                                k < max - (*mjt).second[0]->busIndex; k++){           
                                            np = (*mjt).second[k];
                                            int temp = k - min + (*mjt).second[0]->busIndex;
                                            ((*mit).second[temp]->fanout)++;
                                            (*mit).second[temp]->downNodes.push_back(np);
                                            np->fanin = 1;
                                            np->upperNodes.push_back((*mit).second[temp]);
                                            np->gate = BUFX2;
                                        }
                                    }else{
                                        for(unsigned int k = 0; k < (*mjt).second.size(); k++){
                                            np = (*mjt).second[k];
                                            ((*mit).second[k]->fanout)++;
                                            (*mit).second[k]->downNodes.push_back(np);
                                            np->fanin = 1;
                                            np->upperNodes.push_back((*mit).second[k]);
                                            np->gate = BUFX2;
                                        }
                                    }
                                }
                            }else{
                                boost::trim_right_if(name, boost::is_any_of(",;)"));
                                name.erase(0, (*mit).first.length()+2);
                                boost::trim_left_if(name, boost::is_any_of(" \n"));
                                np = nodeAll[findNode(name)];
                                ((*mit).second[0]->fanout)++;
                                (*mit).second[0]->downNodes.push_back(np);
                                np->fanin = 1;
                                np->upperNodes.push_back((*mit).second[0]);
                                np->gate = BUFX2;
                            }          
                            break;
                        }
                    }
                }
            }
        }
    }
    
    fileHandle.close();
    
    return 0;
}

void printTransform(){
	ofstream fileHandle;
	fileHandle.open("cpu.txt", ofstream::out);

	for(int i = 0; i <= maxLevel; i++){
		for(unsigned int j = 0; j < ptrMatrix[i].size(); j++){
			fileHandle << ptrMatrix[i][j]->name << " ";
		}
		fileHandle << endl;
	}

	fileHandle.close();
}

int main(int argc, char** argv) {
    
    time_t start, end;
    double diff_cpu, diff_gpu;

	if(argc != 3){
		perror("input verilog netlist or vector is missing");
		exit(1);
	}
    
	processModule(string(argv[1])); //parse and elaborate the verilog netlist
//    prepareVector(); //generate random input vector
    nodeLevelize(); //levelize the netlist
    
    transform(); //prepare data strucutre of gMatrix and ptrMatrix
	printTransform();
	partitionBuild(24); //partition at level 24
	printPartition();
	printPartitionPtr();

	time(&start);
    cpuLogicSim(argv[2], 1); //sequential logic simulation on CPU 0->unpartition 1->partition
    time(&end);
    diff_cpu = difftime(end, start);
    printNodeToFile(); //print parse result to file

	//cuda accelerated logic simulation
    time(&start);
//    cudaLogicSim();
    time(&end);
    diff_gpu = difftime(end, start);
//    cudaVerify();
    
    printf("CPU took %.5f seconds to do logic simulation\n", diff_cpu);
    printf("GPU took %.5f seconds to do logic simulation\n", diff_gpu);
    return 0;

}



